# 04 Python常见的编程模式和架构方法 ## 洋葱模型和面向切面(AOP) 在 LangChain 的 Agent 系统和 FastAPI 的 Web 系统中,**洋葱模型 (Onion Model)** 和 **面向切面编程 (AOP)** 是实现功能解耦的核心架构模式。 ### 1. 核心概念:洋葱模型与 AOP * **洋葱模型**:将请求看作一颗洋葱,每一层中间件包裹着核心逻辑。请求进入时由外向内层层穿透,响应返回时由内向外层层回调。这种结构决定了**执行顺序**。 * **面向切面编程 (AOP)**:将非业务逻辑(如权限检查、监控、重试)从业务代码中分离,作为“切面”横向植入系统。它解决了**代码复用**问题。 --- ### 2. FastAPI 中间件:请求/响应层面的“环” FastAPI 基于 Starlette,其中间件工作在 HTTP 协议层: * **场景**:处理整个 HTTP 事务,如 CORS、全局异常捕获、请求计时。 * **实现技巧**:在 `dispatch` 方法中使用 `await call_next(request)`,这行代码就是“剥开下一层洋葱”的动作。 ```python # FastAPI 中的洋葱环 async def dispatch(request: Request, call_next): # 1. 业务逻辑前(外层) start_time = time.time() response = await call_next(request) # 2. 剥开洋葱,执行下一层 # 3. 业务逻辑后(返回路径) process_time = time.time() - start_time return response ``` --- ### 3. LangChain 中间件:Agent 执行层面的“环” LangChain 的 AgentMiddleware 工作在 Agent 的推理循环层,主要处理模型调用和工具调用。 * **场景**:处理 Agent 决策逻辑,如模型切换、工具调用重试、上下文注入。 * **实现技巧**:`wrap_model_call` 中的 `handler(request)` 是剥开下一层洋葱的关键,类似于 `call_next`。 ```python # LangChain 中的洋葱环 @wrap_model_call def retry_middleware(request: ModelRequest, handler: Callable): # 1. 进入切面(可以在此修改 request) for attempt in range(3): try: return handler(request) # 2. 剥开洋葱 except Exception: # 3. 拦截并处理异常 continue ``` --- ### 4. 架构对比表 | 特性 | FastAPI Middleware | LangChain AgentMiddleware | | :----------- | :------------------------ | :---------------------------------- | | **层级** | HTTP 协议/路由层 | Agent 推理/决策层 | | **核心媒介** | `Request` / `Response` | `ModelRequest` / `ModelResponse` | | **触发器** | `call_next` | `handler` (或执行函数) | | **主要用途** | 全局横切逻辑 (CORS, 监控) | 业务行为横切 (模型切换, 提示词优化) | --- ### 5. 最佳实践技巧 1. **分层思维 (Layering)**: * **最外层**:执行全局任务(如日志记录、性能指标、异常处理)。 * **中间层**:处理业务切面(如权限鉴权、动态上下文注入)。 * **最内层**:执行核心逻辑(真正的 LLM 调用或工具运行)。 2. **单一职责原则**:不要在一个中间件里既处理模型切换又处理日志,应分别编写 `DynamicModelMiddleware` 和 `LoggingMiddleware`,然后在 Agent 工厂中按序组合。 3. **状态传递**:在 LangChain 中,利用中间件修改 `request.state` 或返回 `Command`,实现跨层的状态同步,这是 AOP 编程中传递元数据的关键手段。 **结论**: FastAPI 保护的是你的 **Web 接口安全与性能**;LangChain 的中间件保护的是你的 **Agent 推理质量与决策逻辑**。两者虽层级不同,但都通过“执行拦截 -> 调用下层 -> 响应拦截”的洋葱路径,实现了业务逻辑的纯净。 **Relevant docs:** - [Custom middleware](https://docs.langchain.com/oss/python/langchain/middleware/custom) - [FastAPI Middleware documentation](https://fastapi.tiangolo.com/tutorial/middleware/)